/************************************************************************

							Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  							   compressed_filter.h

	$Header: /resource_editor/compressed_filter.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined( COMPRESSED_FILTER_H_INCLUDED )
#define COMPRESSED_FILTER_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <streambuf>
#include <stdexcept>
#include <vector>

#include "constructor_failure.h"
#include "owned_ptr.h"
#include "resource_datatypes.h"
#include "zlib.h"

/////////////////////////////////////////////////////////////////////////////
// deflate filter class

class t_deflate_filter : public std::streambuf
{
public:
	// Types
	typedef t_constructor_failure< t_deflate_filter >	t_create_failure;

	// Constructor
	t_deflate_filter( std::streambuf & buffer, t_int32 datatype = k_medium_compression_binary );
	virtual ~t_deflate_filter();

	// Member functions
	int	close();

private:
	// Data members
	std::streambuf &  		m_dest;
	z_stream				m_zstream;
	t_owned_array< char >	m_buffer;

	unsigned long			m_crc;
	t_int32					m_datatype;

	bool					m_open;

	// Member functions
	char *				get_input_buffer();
	char *				get_output_buffer();
	virtual int_type	overflow( int_type c );
	int_type			overflow_compress( int_type c );
	int_type			overflow_raw( int_type c );
	int					put( unsigned long x );
	virtual int			sync();
	int					sync_compressed();
	int					sync_raw();
};

/////////////////////////////////////////////////////////////////////////////
//	inflate filter class

class t_inflate_filter : public std::streambuf
{
public:
	// Types
	class t_data_error : public std::runtime_error
	{
	private:
		friend class t_inflate_filter;
		t_data_error();
	};

	// Constructor
	t_inflate_filter( std::streambuf & stream_buffer , t_int32 datatype = k_medium_compression_binary);
	virtual ~t_inflate_filter();

	// Member functions
	int	close();

private:
	// Data members
	std::streambuf &		m_source;
	z_stream				m_zstream;
	t_owned_array< char >	m_buffer;
	char *					m_input_buffer;
	char *					m_output_buffer;
	uLong					m_crc;
	t_int32					m_datatype;
	bool					m_is_compressed;
	bool					m_end_of_file;
	bool					m_stream_is_open;
	bool					m_open;
	
	// Member functions
	int					get_char();
	char *				get_input_buffer();
	char *				get_output_buffer();
	int					must_get_char();
	unsigned long		must_get_long();
	void				put_back_char( char c );
	virtual int_type	underflow();
	int_type			underflow_compress();
	int_type			underflow_raw();
};

#endif // !defined( COMPRESSED_FILTER_H_INCLUDED )
